package mutation;

import ga.Individual;

import java.util.*;

import mdr.RecommendGenerator;
import model.StatementKind;
import model.TestClusterBuilder;
import operations.Operation;
import operations.ValuesGenerator;
import util.*;


public class MDRInsertMethodCall extends MutationStrategy {
	Mutation ChangeValueStrategy = GAOperationsConfig.getMutationChangeValueStrategy();
	@Override
	public Individual mutate(Individual individual) {
		RecommendGenerator recommendGenerator=this.gaInfo.getRecommendGenerator();
		Integer trgtBR=-1;
		if(GAConfig.TargetHitBranches)
			trgtBR=MutationFactory.getHitTargetToCover(this.gaInfo);
		else
				trgtBR=MutationFactory.getTargetToCover(this.gaInfo);

//		System.out.println("MDRInsertMethodCall trgtBR: "+ trgtBR+ " " +recommendGenerator.getBranchWithData(trgtBR));
		  List<StatementKind>  BRRelatedStatementList=recommendGenerator.getRecommendMethodsBranch(trgtBR);
//		System.out.println("MDRInsertMethodCall trgtBR: "+ trgtBR+ " " +BRRelatedStatementList);

		if(BRRelatedStatementList.size()==0)
			return individual;
		Individual mutatedIndividual=individual.clone();
		List<Operation> ops =mutatedIndividual.getStatements();
	//	System.err.println("MDRInsertMethodCall individual: "+ ops.size());

		TestClusterBuilder TestCluster=gaInfo.getTestCluster();
		try
		{	
		//	int L=ValuesGenerator.getRandomIntBetween(1,ops.size()-1);
				int randPos = ValuesGenerator.getRandomIntBetween(0,ops.size()-1);
				List<Operation>  rep= new LinkedList<Operation>();
				rep.addAll(ops.subList(0, randPos));
				// See if individual length is reached GAConfig.TestCaseSize
				int L=GAConfig.TestCaseSize-ops.size();
		    	  rep.addAll(Operation.mdrGenerateOperation(gaInfo.getTestCluster(),null,L,BRRelatedStatementList));;

		    	  rep.addAll(ops.subList(randPos, ops.size()));
		    	  ops.clear();
		    	  ops.addAll(rep);

//				if(ValuesGenerator.getBoolean(0.8f)&& GAConfig.Seeding)
//					mutatedIndividual=ChangeValueStrategy.mutateIndividual(mutatedIndividual);


		} catch (Throwable e){
			System.err.println("Insert Random Method Call Class:" + e.getMessage());
		}	

		if(DebugConfig.InsertMethodValueClass){
			Log.log("--------------------individual1----------------------");
			Log.log(individual.toString()+ " size:"+ individual.getSize());
			Log.log("--------------------mutatedIndividual----------------------");
			Log.log(mutatedIndividual.toString()+ " size:"+ mutatedIndividual.getSize());
		}
		
		return mutatedIndividual;
		
	}
	@Override
	public boolean getMutationFlag(int size) {
		if(ValuesGenerator.getBoolean(1.0f/size))
			return true;
		return false;
	}

}
